package com.zr.task.presenter;


import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;

import com.jietong.rfid.util.EPC;
import com.zh.baselibrary.base.BasePresenter;
import com.zh.baselibrary.constant.BaseConstant;
import com.zh.baselibrary.constant.ExtraName;
import com.zh.baselibrary.model.TaskModel;
import com.zh.baselibrary.netutils.BaseResp;
import com.zh.baselibrary.rxjava.RxSubscribe;
import com.zh.baselibrary.utils.IntentUtils;
import com.zh.baselibrary.utils.JsonUtils;
import com.zh.baselibrary.utils.LogUtils;
import com.zh.baselibrary.utils.ShareManager;
import com.zh.baselibrary.utils.TTSUtils;
import com.zh.baselibrary.views.ToastView;
import com.zh.model.Errata;
import com.zh.model.request.LoginInfo;
import com.zh.model.task.SubjectBean;
import com.zh.model.task.error.ErrataSwipeResBean;
import com.zh.model.task.error.ErrorDetailVOBean;
import com.zh.model.task.home.ClassCabinetBean;
import com.zh.model.task.home.CommitBean;
import com.zh.model.task.home.CommitResBean;
import com.zh.model.task.home.ErrataSwipeBean;
import com.zh.model.task.home.RemoteOpenResVO;
import com.zh.model.task.home.SwipingCardBean;
import com.zh.model.task.home.SwipingCardResBean;
import com.zh.model.task.subject.LoginResBean;
import com.zr.andealib.util.LockUtil;
import com.zr.andealib.util.frequency.HighFrequencyCheckUtil;
import com.zr.task.R;
import com.zr.task.activity.CorrigendumDetailActivity;
import com.zr.task.activity.RelationHomeworkActivity;
import com.zr.task.activity.SubjectActivity;
import com.zr.task.adapter.HomeCabinetAdapter;
import com.zr.task.presenter.view.TaskMainView;
import com.zr.task.utils.EquipmentTypeUtils;

import org.greenrobot.eventbus.EventBus;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Semaphore;

import io.reactivex.Observable;

import static android.content.Context.ALARM_SERVICE;

public class TaskMainPresenter extends BasePresenter<TaskMainView> {
    private TaskModel model;
    private LockUtil lockUtil;
    private HighFrequencyCheckUtil util;
    private Timer timer;
    private List<Integer> OpenedDoor = new ArrayList<>();
    private Map<Integer, Set<String>> map = new HashMap<>();
    private Map<Integer, String> stuMap = new HashMap<>();
    private Semaphore semaphore = new Semaphore(1, true);
    private String schoolId;
    private String uuid;
    private int uid;
    private String stuName;
    private int color = 0;
    private boolean isClickedSub = false;
    private int subNum = 0;
    private int openNum = 0;
    private boolean isRemote = false;
    private RemoteOpenResVO remoteOpenResVO;


    public TaskMainPresenter(String schoolId, String uuid) {
        this.schoolId = schoolId;
        this.uuid = uuid;
    }

    //定时关机
    private void sendShutDown() {
        Calendar instance = Calendar.getInstance();
        instance.set(Calendar.HOUR_OF_DAY, 23);//小时
        instance.set(Calendar.MINUTE, 59);//分钟
        instance.set(Calendar.SECOND, 59);//秒
        AlarmManager alarmService = (AlarmManager) getContext().getSystemService(ALARM_SERVICE);
        Intent mIntent = new Intent();
        mIntent.setAction(BaseConstant.SHUT_DOWN);
        PendingIntent broadcast = PendingIntent.getBroadcast(getContext(), 0, mIntent, 0);//通过广播接收
        Long oneDayTime = 24 * 60 * 60 * 1000L;
        Long cha = BaseConstant.timeDifferent;
        if (BaseConstant.timeDifferent / oneDayTime != 0)
            cha = BaseConstant.timeDifferent % oneDayTime;

        alarmService.set(AlarmManager.RTC_WAKEUP, instance.getTimeInMillis() - cha, broadcast);
    }

    @Override
    public void attachModel(Context context) {
        model = new TaskModel(context);
        sendShutDown();
    }

    public void initDevice() {
        lockUtil = new LockUtil();
        lockUtil.init();
        initHigh();
    }

    private void initHigh() {
        if (EquipmentTypeUtils.hasRf(getContext())) {
            if (util == null) {
                util = new HighFrequencyCheckUtil();
                util.connectDev();
            }
        }
    }

    public void beginInvV2() {
        if (EquipmentTypeUtils.hasRf(getContext())) {
            boolean isOpen = false;
            for (int i = 1; i <= EquipmentTypeUtils.getBoxNum(getContext()); i++) {
                boolean isOpenOne = lockUtil.isDoorOPen(i);
                if (isOpenOne) {
                    isOpen = true;
                    if (!OpenedDoor.contains(i)) {
                        OpenedDoor.add(i);
                    }
                }
            }
            if (!isOpen) {
                util.beginInvV2();
            }
        }
    }

    public void stopInvV2() {
        if (EquipmentTypeUtils.hasRf(getContext())) {
            if (util != null)
                util.stopInvV2();
        }
    }

    public void setColor(int color) {
        this.color = color;
    }

    //柜子详细
    public void getCabinetDetail() {
        Observable<BaseResp<ClassCabinetBean>> observable = getObservableNotStop(model.detail(schoolId, uuid));
        observable.retry(2).subscribe(new RxSubscribe<BaseResp<ClassCabinetBean>>() {
            @Override
            public void onSuccess(BaseResp<ClassCabinetBean> baseResp) throws Exception {
                if (baseResp.getCode() == 0) {
                    ShareManager.setValue(getContext(), BaseConstant.LOCAL_CAB_LIST, JsonUtils.objectToString(baseResp.getData()));
                    if (!TextUtils.isEmpty(baseResp.getData().getType())) {
                        ShareManager.setValue(getContext(), BaseConstant.DEVICE_TYPE, baseResp.getData().getType());
                        EquipmentTypeUtils.reSet();
                        initHigh();
                        getView().initMore();
                        beginInvV2();
                    }
                    ShareManager.setInt(getContext(), BaseConstant.DEVICE_VOICE, baseResp.getData().getVoiceSwitch());
                    BaseConstant.canSpeak = baseResp.getData().getVoiceSwitch() == 1;
                    getView().upViewHome(baseResp.getData());
                } else {
                    ClassCabinetBean mBean = JsonUtils.stringToObject(ShareManager.getValue(getContext(), BaseConstant.LOCAL_CAB_LIST), ClassCabinetBean.class);
                    getView().upViewHome(mBean);
                }

            }

            @Override
            public void onHint(String hint) {
                ClassCabinetBean mBean = JsonUtils.stringToObject(ShareManager.getValue(getContext(), BaseConstant.LOCAL_CAB_LIST), ClassCabinetBean.class);
                getView().upViewHome(mBean);
            }
        });

    }

    //远程开箱
    public void remoteOpen(RemoteOpenResVO remoteOpenResVO) {
        isRemote = true;
        this.remoteOpenResVO = remoteOpenResVO;
        getView().setClickType(1);
        stuName = "";
        stopInvV2();
        openDoor(remoteOpenResVO.getCabinetNum());
    }

    //远程开箱结果和提示
    public void openResult(int num, int code) {
        if (isRemote) {
            if (code == 0) {
                TTSUtils.getInstance().speak(getContext().getString(R.string.open_normal));
                ToastView.showLong("柜门已开启，取出作业后请关闭");
            }
            isRemote = false;
            remoteOpenResVO.setCode(code);
            LogUtils.e("" + JsonUtils.objectToString(remoteOpenResVO));
            Observable<BaseResp<Object>> observable = getObservableNotStop(model.remoteOpenResult(remoteOpenResVO));
            observable.subscribe(new RxSubscribe<BaseResp<Object>>() {
                @Override
                public void onSuccess(BaseResp<Object> objectBaseResp) throws Exception {
                }

                @Override
                public void onHint(String hint) {
                }
            });
        } else {
            if (code == 0) {
                ToastView.showLong("课代表" + stuName + "科目柜门已打开，请取出作业");
                int error = getErrorNum(num);
                if (error == 0)
                    TTSUtils.getInstance().speak(getContext().getString(R.string.open_normal));
                else {
                    String tip = getContext().getString(R.string.open_error) + error + getContext().getString(R.string.unit);
                    TTSUtils.getInstance().speak(tip);
                }
                openSuccess();

            }
        }
    }

    private int getErrorNum(int box) {
        int uiBoxNum = hardNumToUi(box);
        if (uiBoxNum > getView().getAdapter().getItem().size() - 1 || getView().getAdapter() == null || getView().getAdapter().getItem() == null || getView().getAdapter().getItem().get(uiBoxNum) == null)
            return 0;
        else
            return getView().getAdapter().getItem().get(uiBoxNum).getMissentCount();
    }

    private void openSuccess() {
        Observable<BaseResp<Object>> observable = getObservable(model.openSuccess(new Errata(schoolId, 1, uid + "")));
        observable.subscribe(new RxSubscribe<BaseResp<Object>>() {
            @Override
            public void onSuccess(BaseResp<Object> objectBaseResp) throws Exception {
            }

            @Override
            public void onHint(String hint) {
            }
        });
    }

    //课代表磁卡登录
    public void checkCard(String cardCode) {
        Observable<BaseResp<LoginResBean>> observable = getObservable(model.login(schoolId, new LoginInfo(cardCode, uuid, 0)));
        observable.subscribe(new RxSubscribe<BaseResp<LoginResBean>>() {
            @Override
            public void onSuccess(BaseResp<LoginResBean> loginResBeanBaseResp) throws Exception {
                if (!BaseConstant.hasNet)
                    EventBus.getDefault().post(274);
                getView().dismissDialog();
                LoginResBean info = loginResBeanBaseResp.getData();
                uid = info.getId();
                if (info.getCabinetDetailVOList().size() == 0) {
                    ToastView.showLong("该作业柜无您的科目");
                } else if (info.getCabinetDetailVOList().size() == 1) {
                    //直接打开
                    SubjectBean mBean = info.getCabinetDetailVOList().get(0);
                    stuName = info.getName() + "，" + mBean.getSubjectName();
                    openDoor(mBean.getCabinetNum());
                } else {
                    //切换
                    TTSUtils.getInstance().speak(getContext().getString(R.string.choose_subject));
                    getView().initSubject(info);
                }
            }

            @Override
            public void onHint(String hint) {
                ToastView.showShort(hint);
                getView().dismissDialog();
            }
        });
    }

    //勘误刷卡
    public void errataSwipe(String cardCode) {
        Observable<BaseResp<com.zh.model.task.error.ErrataSwipeResBean>> observable = getObservable(model.errataSwipe(new ErrataSwipeBean(cardCode, uuid)));
        observable.subscribe(new RxSubscribe<BaseResp<ErrataSwipeResBean>>() {
            @Override
            public void onSuccess(BaseResp<ErrataSwipeResBean> errataSwipeResBeanBaseResp) throws Exception {
                getView().dismissDialog();
                ErrataSwipeResBean mBean = errataSwipeResBeanBaseResp.getData();
                if (mBean == null || mBean.getSubjectVOS().size() == 0) {
                    ToastView.showLong("没有误投记录，无需勘误");
                    TTSUtils.getInstance().speak(getContext().getString(R.string.no_error));
                    beginInvV2();

                    return;
                }
                Bundle bundle = new Bundle();
                if (mBean.getSubjectVOS().size() > 1) {
                    bundle.putSerializable(ExtraName.KEY_DATA, mBean);
                    IntentUtils.instance().startActivity(getContext(), SubjectActivity.class, bundle);
                } else {
                    if (mBean.getSubjectVOS().get(0) != null) {
                        bundle.putSerializable(ExtraName.KEY_DATA, new ErrorDetailVOBean(mBean.getSubjectVOS().get(0).getCabinetNum(), uuid, mBean.getStudentId()));
                        bundle.putInt(ExtraName.KEY_COLOR, color);
                        IntentUtils.instance().startActivity(getContext(), CorrigendumDetailActivity.class, bundle);
                    }
                }
            }

            @Override
            public void onHint(String hint) {
                getView().dismissDialog();
                beginInvV2();
            }
        });
    }

    //关联
    public void swipingCard(String cardCode) {
        Observable<BaseResp<SwipingCardResBean>> observable = getObservable(model.swipingCard(new SwipingCardBean(cardCode, schoolId)));
        observable.subscribe(new RxSubscribe<BaseResp<SwipingCardResBean>>() {
            @Override
            public void onSuccess(BaseResp<SwipingCardResBean> swipingCardResBeanBaseResp) throws Exception {
                getView().dismissDialog();
                Bundle bundle = new Bundle();
                bundle.putSerializable(ExtraName.KEY_DATA, swipingCardResBeanBaseResp.getData());
                bundle.putInt(ExtraName.KEY_COLOR, color);
                IntentUtils.instance().startActivity(getContext(), RelationHomeworkActivity.class, bundle);
            }

            @Override
            public void onHint(String hint) {
                ToastView.showShort(hint);
                getView().dismissDialog();
                beginInvV2();
            }
        });
    }

    //boxNum硬件
    public void complete(boolean isEmergency, int boxNum) {

        HomeCabinetAdapter adapter = getView().getAdapter();
        int uiNum = hardNumToUi(boxNum);
        if (getView().getAdapter() == null || getView().getAdapter().getItem() == null || uiNum > getView().getAdapter().getItem().size() - 1 || getView().getAdapter().getItem().get(uiNum) == null)
            return;
        int cabinetNum = adapter.getItem().get(uiNum).getCabinetNum();
        CommitBean mBean = new CommitBean();
        mBean.setEquipmentCode(uuid);
        mBean.setCabinetNum(cabinetNum);
        if (isEmergency) {
            if (!BaseConstant.hasNet) {
                ShareManager.setValue(getContext(), BaseConstant.LOCAL_ERROR_COMPLETE + boxNum, JsonUtils.objectToString(mBean));
            }
        } else {
            Observable<BaseResp<Object>> observable = getObservableNotStop(model.complete(schoolId, mBean));
            observable.retry(2).subscribe(new RxSubscribe<BaseResp<Object>>() {
                @Override
                public void onSuccess(BaseResp<Object> objectBaseResp) throws Exception {
                    if (objectBaseResp.getCode() == 0) {
                        adapter.getItem().get(uiNum).setCount(0);
                        //    adapter.getItem().get(uiNum).setMissentCount(0);
                        adapter.notifyDataSetChanged();
                        ShareManager.setValue(getContext(), BaseConstant.LOCAL_ERROR_COMPLETE + boxNum, "");
                    } else {
                        ToastView.showLong(objectBaseResp.getMsg());
                    }
                }

                @Override
                public void onHint(String hint) {
                    if (!BaseConstant.hasNet) {
                        ShareManager.setValue(getContext(), BaseConstant.LOCAL_ERROR_COMPLETE + boxNum, JsonUtils.objectToString(mBean));
                        adapter.getItem().get(uiNum).setCount(0);
                        //     adapter.getItem().get(uiNum).setMissentCount(0);
                        adapter.notifyDataSetChanged();
                    }
                }
            });
        }
    }

    private boolean isToNet = true;

    // rfid提交
    public void commit(EPC epc) {
        int boxNum;
        int ant = Integer.parseInt(epc.getAnt());
        int total = EquipmentTypeUtils.getBoxNum(getContext());
        if (total <= 2) {
            boxNum = ant;
        } else {
            if (ant % 2 != 0)
                ant++;
            boxNum = (20 - ant) / 2 + 1;
        }

        Set<String> set = map.get(boxNum);  //硬件地址
        if (!(null != set && set.contains(epc.getEpc()))) {  //未提交过
//            if (!BaseConstant.hasNet) { //无网络
//                Set<String> setNet = map.get(boxNum);
//                if (setNet == null) {
//                    setNet = new HashSet<>();
//                }
//                setNet.add(epc.getEpc());
//                map.put(boxNum, setNet);
//                return;
//            }
            int uiBoxNum = hardNumToUi(boxNum);
            if (getView().getAdapter() == null || getView().getAdapter().getItem() == null ||uiBoxNum > getView().getAdapter().getItem().size() - 1 ||  getView().getAdapter().getItem().get(uiBoxNum) == null)
                return;
            if (isToNet) {
                isToNet = false;
                List<String> list = new ArrayList<>();
                list.add(epc.getEpc());
                CommitBean mBean = new CommitBean();
                mBean.setEquipmentCode(uuid);
                mBean.setCabinetNum(getView().getAdapter().getItem().get(uiBoxNum).getCabinetNum());
                mBean.setRadioCodes(list);
                Observable<BaseResp<CommitResBean>> observable = getObservableNotStop(model.commit(schoolId, mBean));
                observable.subscribe(new RxSubscribe<BaseResp<CommitResBean>>() {
                    @Override
                    public void onSuccess(BaseResp<CommitResBean> commitResBeanBaseResp) throws Exception {
                        isToNet = true;
                        if (commitResBeanBaseResp.getCode() == -999)
                            return;
                        Set<String> set = map.get(boxNum);
                        if (set == null) {
                            set = new HashSet<>();
                        }
                        set.add(list.get(0));
                        map.put(boxNum, set);

                        CommitResBean mBean = commitResBeanBaseResp.getData();
                        if (mBean != null) {
                            if (TextUtils.isEmpty(mBean.getErrMsg())) {
                                TTSUtils.getInstance().speak(getContext().getString(R.string.submit_success));
                                ToastView.showLong("作业提交成功");
                            } else {
                                if(mBean.getErrMsg().equals("作业投递有误，请勘误取出重新投放")) {
                                    TTSUtils.getInstance().speak(getContext().getString(R.string.submit_error));
                                    ToastView.showLong(mBean.getErrMsg());
                                    int count = getView().getAdapter().getItem().get(uiBoxNum).getMissentCount();
                                    getView().getAdapter().getItem().get(uiBoxNum).setMissentCount(count + 1);
                                    getView().getAdapter().notifyDataSetChanged();
                                }else {
                                    TTSUtils.getInstance().speak(mBean.getErrMsg()+",请取回");
                                    ToastView.showLong(mBean.getErrMsg());
                                }

                            }
                            if (mBean.getCount() != null && mBean.getCount() != 0) {
                                //更新数据到界面
                                getView().getAdapter().getItem().get(hardNumToUi(boxNum)).setCount(mBean.getCount());
                                getView().getAdapter().notifyDataSetChanged();
                            }
                        } else {
                            ToastView.showLong(commitResBeanBaseResp.getMsg());
                        }
                    }

                    @Override
                    public void onHint(String hint) {
                        if (!BaseConstant.hasNet) { //无网络
                            Set<String> setNet = map.get(boxNum);
                            if (setNet == null) {
                                setNet = new HashSet<>();
                            }
                            setNet.add(epc.getEpc());
                            map.put(boxNum, setNet);
                            return;
                        }
                        isToNet = true;
                        LogUtils.e(hint);
                        ToastView.showLong(hint);

                    }
                });
            }
        }

    }


    public int getOpenNum() {
        return openNum;
    }

    //开门服务端地址
    private void openDoor(int boxNum) {
        boxNum = softToHardNum(boxNum);
        openNum = boxNum;
        lockUtil.openDoor(boxNum);
        Set<String> set = map.get(boxNum);
        if (set != null)
            set.clear();
        map.put(boxNum, set);
        stuMap.put(boxNum, stuName.split("，")[0]);

    }

    //勘误完成
    public void errorComplete(Intent intent) {
        Set<String> set = (Set<String>) intent.getSerializableExtra(ExtraName.KEY_DATA);
        Integer boxNum = intent.getIntExtra(ExtraName.KEY_TRAN_DATA, -1); //服务端柜号
        boxNum = softToHardNum(boxNum);
        if (boxNum != -1 && map != null && map.size() > 0 && map.get(boxNum) != null) {
            map.get(boxNum).removeAll(set);
        }
        int uiBoxNum = hardNumToUi(boxNum);
        if (getView().getAdapter() == null || getView().getAdapter().getItem() == null ||uiBoxNum > getView().getAdapter().getItem().size() - 1 ||  getView().getAdapter().getItem().get(uiBoxNum) == null)
            return;
        getView().getAdapter().getItem().get(uiBoxNum).setMissentCount(0);
        getView().getAdapter().notifyDataSetChanged();
    }


    public boolean isClickedSub() {
        return isClickedSub;
    }

    public void setClickedSub(boolean clickedSub) {
        isClickedSub = clickedSub;
        subNum = 0;
    }

    //多科目点击
    public void subClick(SubjectBean subjectBean, String name) {
        if (!isClickedSub) {
            isClickedSub = true;
            stuName = name + "，" + subjectBean.getSubjectName();
            subNum = softToHardNum(subjectBean.getCabinetNum());
            openDoor(subjectBean.getCabinetNum());
        } else {
            ToastView.showLong("请取出作业关闭柜门后重新登录再取作业");
        }
    }

    private int[] deviceToUI8N = {0, 0, 3, 6, 4, 7, 2, 5, 8};
    private int[] deviceToUI11N = {0, 0, 4, 8, 5, 9, 2, 6, 10, 3, 7, 11};

    private int hardNumToUi(int boxNum) {
        int totalNum = EquipmentTypeUtils.getBoxNum(getContext());
        if (boxNum <= totalNum) {
            if (totalNum == 1)
                return 0;
            else if (totalNum == 2)
                return boxNum;
            else if (totalNum == 8)
                return deviceToUI8N[boxNum];
            else
                return deviceToUI11N[boxNum];
        } else {
            ToastView.showLong("物理编号与界面编号对应不上");
            return boxNum;
        }
    }

    private int[] cabinetNumToDevice8N = {0, 1, 6, 2, 4, 7, 3, 5, 8};
    private int[] cabinetNumToDevice11N = {0, 1, 6, 9, 2, 4, 7, 10, 3, 5, 8, 11};

    private int softToHardNum(int boxNum) {
        int totalNum = EquipmentTypeUtils.getBoxNum(getContext());
        if (boxNum <= totalNum) {
            if (totalNum <= 2)
                return boxNum;
            else if (totalNum == 8)
                return cabinetNumToDevice8N[boxNum];
            else
                return cabinetNumToDevice11N[boxNum];
        } else {
            ToastView.showLong("物理编号与界面编号对应不上");
            return boxNum;
        }
    }

    //检测关门
    public void checkDoorClose(int num, boolean showOpen) {
        if (showOpen)
            openResult(num, 0);
        try {
            semaphore.acquire();
            if (!OpenedDoor.contains(num)) {
                OpenedDoor.add(num);
            }
            semaphore.release();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (OpenedDoor.size() == 1) {
            if (timer == null)
                timer = new Timer();
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    for (int i = 0; i < OpenedDoor.size(); i++) {

                        try {
                            semaphore.acquire();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        int boxNum = OpenedDoor.get(i);
                        semaphore.release();
                        boolean isOpen = lockUtil.isDoorOPen(boxNum);
                        if (!isOpen) {
                            OpenedDoor.remove(i);
                            i--;
                            //关门操作
                            String tip = "";
                            if (getView().getClickType() == 2) {
                                tip = "已取出误投作业，请重新投递";
                            } else {
                                complete(false, boxNum);
                                String name = stuMap.get(boxNum);
                                if (TextUtils.isEmpty(name))
                                    tip = "作业已全部取出";
                                else
                                    tip = "科代表" + name + "，作业已全部取出";
                            }
                            if (isClickedSub) {
                                if (subNum == boxNum) {
                                    getView().hideSubject();
                                }
                            }
                            getView().doorClose(tip);

                        }
                    }
                    if (OpenedDoor.size() == 0) {
                        timer.cancel();
                        timer.purge();
                        timer = null;
                    }
                }
            }, 0, 500);
        }
    }
}
